<!DOCTYPE html>
<html>
<head>
<title>GT02A</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
<script src=http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js></script>
<script src=http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js></script>
<script src=http://jpp.googlecode.com/svn/jquery/plugins/jquery.sparkline-2.0.min.js></script>
<script>
GT02A = top.Tian.Class(top.Tian.Embeded, {
    dictionaries: {
        'en': {
            "nav-realtime": "Realtime Status",
            "nav-history": "Historical Data",
            "btn-1day": "Latest 1 day",
            "btn-3day": "Latest 3 days",
            "btn-7day": "Latest 7 days",
            "btn-load": "Load",
            "btn-remove": "Remove",
            "status-lon": "Longitude (deg)",
            "status-lat": "Latitude (deg)",
            "status-cou": "Course (deg)",
            "status-vel": "Velocity (km/h)",
            "track-label": "Track",
            "odometer": 'Odometer',
            "t0_lable": "From time:",
            "t1_lable": "To time:",
            "feature-vel": "Velocity"
        },
        'zh-CN': {
            "nav-realtime": "实时状态",
            "nav-history": "历史数据",
            "btn-1day": "最近一天",
            "btn-3day": "最近三天",
            "btn-7day": "最近七天",
            "btn-load": "加载",
            "btn-remove": "清除",
            "status-lon": "经度 (度)",
            "status-lat": "维度 (度)",
            "status-cou": "航向 (度)",
            "status-vel": "航速 (km/h)",
            "track-label": "跟踪",
            "odometer": '里程',
            "t0_lable": "起始时间：",
            "t1_lable": "终止时间：",
            "feature-vel": "航速"
        }
    },
    
    $datetime: null,
    $statusPOW: null,
    $statusGSM: null,
    $statusGPS: null,
    $statusLon: null,
    $statusLat: null,
    $statusCou: null,
    $statusVel: null,
    
    loadTimer: null,
    loadTimeout: 15000,
    
    trackLayer: null,
    featureTrack: null,
    featureSlider: null,
    
    onRun: function () {
        top.Tian.Embeded.prototype.onRun.apply(this, arguments);
        
        // internationalization
        $("span[id='nav-realtime']").text(this.i18n('nav-realtime'));
        $("span[id='nav-history']").text(this.i18n('nav-history'));
        $("#data-period option[value='1']").text(this.i18n('btn-1day'));
        $("#data-period option[value='3']").text(this.i18n('btn-3day'));
        $("#data-period option[value='7']").text(this.i18n('btn-7day'));
        $("span[id='btn-load']").text(this.i18n('btn-load'));
        $("span[id='btn-remove']").text(this.i18n('btn-remove'));
        $("#status-lon_label").text(this.i18n('status-lon'));
        $("#status-lat_label").text(this.i18n('status-lat'));
        $("#status-cou_label").text(this.i18n('status-cou'));
        $("#status-vel_label").text(this.i18n('status-vel'));
        $("#track-label").text(this.i18n('track-label'));
        $("#t0_lable").text(this.i18n('t0_lable'));
        $("#t1_lable").text(this.i18n('t1_lable'));
        var dt = new Date();
        $('#t1').val(top.Tian.Date.format(dt, 'yyyy-mm-dd HH:MM:SS'));
        dt.setTime(dt.getTime() - 86400000);
        $('#t0').val(top.Tian.Date.format(dt, 'yyyy-mm-dd HH:MM:SS'));
        
        $('#load-data').bind('click', top.Tian.Function.bind(this.onLoadData, this));
        $('#remove-data').bind('click', top.Tian.Function.bind(this.onRemoveData, this));
        
        $('#check-track').live('change', top.Tian.Function.bind(this.onTrackChange, this));
        $('#data-period').live('change', top.Tian.Function.bind(this.onPeriodChange, this));
        $('#data-slider').live('change', top.Tian.Function.bind(this.onSliderChange, this));
        
        this.$datetime = $('#datetime');
        this.$statusPOW = $('#status-pow');
        this.$statusGSM = $('#status-gsm');
        this.$statusGPS = $('#status-gps');
        this.$statusLon = $('#status-lon');
        this.$statusLat = $('#status-lat');
        this.$statusCou = $('#status-cou');
        this.$statusVel = $('#status-vel');
        
        this.updateStatus({spow: 0, sgsm: 0, sgps: 0});
        
        // initialize with last data
        this.onSocketDeviceData({devicedata: this.theApp.getLastDeviceData()});
        // register events
        this.theApp.getEvents().register('socketdevicedata', this, this.onSocketDeviceData);
        
        // create track layer
        this.trackLayer = new top.OpenLayers.Layer.Vector(this.theApp.getTitle());
        this.theApp.getOS().getMap().addLayer(this.trackLayer);
    },
    
    destroy: function() {
        $('#check-track, #data-slider, #data-period, #load-data, #remove-data').unbind();
        this.theApp.getEvents().unregister('socketdevicedata', this, this.onSocketDeviceData);
        
        this.featureTrack && this.featureTrack.destroy();
        this.featureTrack = null;
        this.featureSlider && this.featureSlider.destroy();
        this.featureSlider = null;
        this.trackLayer.destroy();
        this.trackLayer = null;
        
        if (this.loadTimer) {
            clearTimeout(this.loadTimer);
            this.loadTimer = null;
        }
        
        this.$datetime = null;
        this.$statusPOW = null;
        this.$statusGSM = null;
        this.$statusGPS = null;
        this.$statusLon = null;
        this.$statusLat = null;
        this.$statusCou = null;
        this.$statusVel = null;
        
        top.Tian.Embeded.prototype.destroy.apply(this, arguments);
    },
    
    onTrackChange: function(event) {
        if ($('#check-track').attr('checked')) {
            // start track
            if (!this.featureTrack) {
                this.featureTrack = new top.OpenLayers.Feature.Vector(
                    new top.OpenLayers.Geometry.LineString([this.theApp.feature.geometry.clone()]),
                    null, {
                        strokeColor: "#0000ff",
                        strokeWidth: 3
                });
                this.trackLayer.addFeatures([this.featureTrack], {silent: true});
                $("#track-label").text(this.i18n('track-label') + ' ' + this.i18n('odometer') + ': 0 km');
            }
        } else {
            // stop track
            if (this.featureTrack) {
                this.trackLayer.removeFeatures([this.featureTrack], {silent: true});
                this.featureTrack.destroy();
                this.featureTrack = null;
                $("#track-label").text(this.i18n('track-label'));
            }
        }
    },
    
    onPeriodChange: function(event) {
        var dt = new Date();
        $('#t1').val(top.Tian.Date.format(dt, 'yyyy-mm-dd HH:MM:SS'));
        dt.setTime(dt.getTime() - 86400000*parseInt($('#data-period').val(), 10));
        $('#t0').val(top.Tian.Date.format(dt, 'yyyy-mm-dd HH:MM:SS'));
    },
    
    onLoadData: function(event) {
        var t0 = $('#t0').val(), t1 = $('#t1').val();
        if (!t0 || !t1 || t1 <= t0 || this.loadTimer || !this.theApp) {
            $('#t0, #t1').val(top.Tian.Date.format(new Date(), 'yyyy-mm-dd HH:MM:SS'));
            return;
        }
        
        t0 = new Date(t0.replace(' ', 'T') + 'Z');
        t1 = new Date(t1.replace(' ', 'T') + 'Z');
        if (!t0 || !t1 || isNaN(t0.getTime()) || isNaN(t1.getTime())) {
            $('#t0, #t1').val(top.Tian.Date.format(new Date(), 'yyyy-mm-dd HH:MM:SS'));
            return;
        }
        
        this.theApp.getEvents().triggerEvent('appdevicedata', {devicedata: {
            type: 'devicehtdata',
            key: this.theApp.getKey(),
            t0: t0.getTime(), // in ms
            t1: t1.getTime()
        }});
        $.mobile.showPageLoadingMsg();
        this.loadTimer = setTimeout(top.Tian.Function.bind(this.onLoadTimeout, this), this.loadTimeout);
    },
    
    onLoadTimeout: function() {
        $.mobile.hidePageLoadingMsg();
        clearTimeout(this.loadTimer);
        this.loadTimer = null;
    },
    
    onRemoveData: function(event) {
        this.trackLayer.removeAllFeatures({silent: true});
        this.featureSlider = null;
        // reset slider
        $('#data-slider').attr('value', 0).attr('max', 0).slider('refresh');
    },
    
    onSliderChange: function(event, ui) {
        var idx = $('#data-slider').attr('value');
        
        // move feature on map
        if (idx >= 0 && this.featureSlider && idx < this.featureSlider.attributes.data.length) {
            var line = new top.OpenLayers.Geometry.LineString(this.featureSlider.attributes.points.slice(0, idx));
            var odom = top.Tian.Number.limitFixDigs(line.getGeodesicLength(
                            this.theApp.getOS().getMap().getProjectionObject()
                       )/1000, 1);
            this.featureSlider.style.label = this.theApp.getTitle() + '\n' +
                top.Tian.Date.format(
                    new Date(this.featureSlider.attributes.data[idx].time), 'yyyy-mm-dd HH:MM:SS') + '\n' +
                this.i18n('feature-vel') + ': ' + this.featureSlider.attributes.data[idx].speed + ' km/h, ' +
                this.i18n('odometer') + ': ' + odom + ' km', 
            this.featureSlider.style.rotation = this.featureSlider.attributes.data[idx].angle;
            this.featureSlider.geometry.x = this.featureSlider.attributes.points[idx].x;
            this.featureSlider.geometry.y = this.featureSlider.attributes.points[idx].y;
            this.featureSlider.geometry.calculateBounds();
            this.featureSlider.layer && this.featureSlider.layer.drawFeature(this.featureSlider);
        }
    },
    
    onSocketDeviceData: function(event) {
        if (!event || !event.devicedata) {
            return;
        }
        
        var data = event.devicedata;
        if (data.type === 'devicertdata') {
            // update status
            this.updateStatus(data);
        } else if (data.type === 'devicehtdata') {
            // reset timer
            if (this.loadTimer) {
                clearTimeout(this.loadTimer);
                this.loadTimer = null;
            }
            $.mobile.hidePageLoadingMsg();
            // set data
            if (top.Tian.Array.isArray(data.htdata) && data.htdata.length>0) {
                this.updateTrack(data.htdata);
            }
        }
    },
    
    // data = {
    //      time, // timestamp in ms
    //      lonlat, // []
    //      angle, // course
    //      speed, // velocity
    //      spow, sgsm, sgps
    //}
    updateStatus: function(data) {
        var dt = data.time ? new Date(data.time) : new Date();
        this.$datetime.text(top.Tian.Date.format(dt, 'yyyy-mm-dd HH:MM:SS'));
        
        // power status 0 ~ 6
        if (typeof data.spow === 'number') {
            if (data.spow <= 0) { // empty
                this.$statusPOW.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#f00', '#f00']});
            } else if (data.spow >= 6) { // full
                this.$statusPOW.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#008000', '#008000']});
            } else {
                this.$statusPOW.sparkline([data.spow, 6 - data.spow],
                    {type: 'pie', offset: -90, sliceColors: [(data.spow > 2 ? '#008000' : '#f00'), '#ddd']});
            }
        }
        
        // gsm status 0 ~ 4
        if (typeof data.sgsm === 'number') {
            if (data.sgsm <= 0) { // empty
                this.$statusGSM.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#f00', '#f00']});
            } else if (data.sgsm >= 4) { // full
                this.$statusGSM.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#008000', '#008000']});
            } else {
                this.$statusGSM.sparkline([data.sgsm, 4 - data.sgsm],
                    {type: 'pie', offset: -90, sliceColors: [(data.sgsm > 1 ? '#008000' : '#f00'), '#ddd']});
            }
        }
        
        // gps status 0 ~ 12
        if (typeof data.sgps === 'number') {
            if (data.sgps <= 0) { // empty
                this.$statusGPS.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#f00', '#f00']});
            } else if (data.sgps >= 12) { // full
                this.$statusGPS.sparkline([1, 1], {type: 'pie', offset: -90, sliceColors: ['#008000', '#008000']});
            } else {
                this.$statusGPS.sparkline([data.sgps, 12 - data.sgps],
                    {type: 'pie', offset: -90, sliceColors: [(data.sgps > 4 ? '#008000' : '#f00'), '#ddd']});
            }
        }
        
        // lonlat
        if (top.Tian.Array.isArray(data.lonlat) && data.lonlat.length === 2) {
            this.$statusLon.text(data.lonlat[0]);
            this.$statusLat.text(data.lonlat[1]);
            
            // update track feature
            if (this.featureTrack) {
                var point = new top.OpenLayers.Geometry.Point(data.lonlat[0], data.lonlat[1]).transform(
                    this.theApp.getOS().getMap().displayProjection,
                    this.theApp.getOS().getMap().getProjectionObject()
                );
                this.featureTrack.geometry.addPoint(point);
                this.featureTrack.geometry.calculateBounds();
                this.featureTrack.layer && this.featureTrack.layer.drawFeature(this.featureTrack);
                $("#track-label").text(
                    this.i18n('track-label') + ' ' + this.i18n('odometer') + ': ' +
                    top.Tian.Number.limitFixDigs(
                        this.featureTrack.geometry.getGeodesicLength(
                            this.theApp.getOS().getMap().getProjectionObject()
                        )/1000, 1) + ' km'
                );
            }
        }
        
        // course
        if (typeof data.angle === 'number') {
            this.$statusCou.text(data.angle);
        }
        
        // velocity
        if (typeof data.speed === 'number') {
            this.$statusVel.text(data.speed);
        }
    },
    
    updateTrack: function(data) {
        var epochData = null, points = [], i = 0, len = data.length;
        
        // reset slider
        $('#data-slider').attr('value', 0).attr('max', len).slider('refresh');
        this.trackLayer.removeAllFeatures({silent: true});
        this.featureSlider = null;
        
        for (i=0; i<len; i++) {
            epochData = data[i];
            points.push(new top.OpenLayers.Geometry.Point(
                        epochData.lonlat[0], epochData.lonlat[1]
            ).transform(
                        this.theApp.getOS().getMap().displayProjection,
                        this.theApp.getOS().getMap().getProjectionObject()
            ));
        }
        
        // plot on map
        var featureTrack = new top.OpenLayers.Feature.Vector(new top.OpenLayers.Geometry.LineString(points), null, {
            strokeColor: "#0000ff",
            strokeWidth: 3
        });
        this.featureSlider = new top.OpenLayers.Feature.Vector(points[0].clone(), {data: data, points: points}, {
                    pointRadius: 8,
                    graphicName:'triangle',
                    rotation: data[0].angle,
                    strokeColor: "#008000",
                    strokeWidth: 2,
                    fillColor: '#00ff00',
                    fillOpacity: 0.618,
                    label: this.theApp.getTitle() + '\n' +
                            top.Tian.Date.format(new Date(data[0].time), 'yyyy-mm-dd HH:MM:SS') + '\n' +
                            this.i18n('feature-vel') + ': ' + data[0].speed + ' km/h, ' +
                            this.i18n('odometer') + ': 0 km',
                    labelAlign: 'lm',
                    labelXOffset: 15,
                    fontColor: "#008000",
                    fontSize: "12px"
        });
        this.trackLayer.addFeatures([featureTrack, this.featureSlider]);
            
        // reset map
        var extent = this.trackLayer.getDataExtent();
        if (extent) {
            this.theApp.getOS().getMap().zoomToExtent(extent);
        }
    },

    CLASS_NAME: "GT02A"
});

function tianMain(options) {
    return new GT02A(options);
}
</script>

<style type="text/css">
body {
    font-size: 16px;
}
table {
    border: solid 1px black;
}
td {
    border: solid 1px gray;
    padding: 5px;
}
</style>
</head>

<body>

<div data-role="page" data-theme="d" id="page-realtime">
    <div data-role="header" data-position="inline">
        <h1><span id="nav-realtime"></span></h1>
        <a id="btn-history" href="#page-history" class="ui-btn-right" data-icon="arrow-r" data-iconpos="right" data-transition="slide"><span id="nav-history"></span></a>
    </div>
    <div data-role="content">
        <div><span id='datetime'></span></div>
        <p>Power <span id="status-pow"></span> GSM <span id="status-gsm"></span> GPS <span id="status-gps"></span></p>
        <table>
            <tr>
                <td id="status-lon_label"></td>
                <td id="status-lat_label"></td>
                <td id="status-cou_label"></td>
                <td id="status-vel_label"></td>
            </tr>
            <tr>
                <td id="status-lon">----</td>
                <td id="status-lat">----</td>
                <td id="status-cou">----</td>
                <td id="status-vel">----</td>
            </tr>
        </table>
        <p>
            <label><input type="checkbox" name="check-track" id="check-track" /><span id="track-label"></span></label>
        </p>
    </div>
</div>

<div data-role="page" data-theme="d" id="page-history">
    <div data-role="header" data-position="inline">
        <a id="btn-realtime" href="#page-realtime" class="ui-btn-left" data-icon="arrow-l" data-iconpos="left" data-transition="slide" data-direction="reverse"><span id="nav-realtime"></span></a>
        <h1><span id="nav-history"></span></h1>
    </div>
    <div data-role="content">
        <div data-role="fieldcontain">
            <label id="t0_lable" for="t0"></label>
            <input type="text" name="t0" id="t0" value="" />
        </div>
        <div data-role="fieldcontain">
            <label id="t1_lable" for="t1"></label>
            <input type="text" name="t1" id="t1" value="" />
        </div>
        <div>
            <div class="ui-btn ui-btn-inline">
            <select id="data-period" data-inline="true" data-mini="true" data-icon="arrow-d" data-iconpos="left" data-native-menu="false">
                <option value="1"></option>
                <option value="3"></option>
                <option value="7"></option>
            </select>
            </div>
            <a id="load-data" href="#" data-role="button" data-inline="true" data-mini="true" data-icon="check"><span id="btn-load"></span></a>
            <a id="remove-data" href="#" data-role="button" data-inline="true" data-mini="true" data-icon="delete"><span id="btn-remove"></span></a>
        </div>
        <p>
            <input type="range" id="data-slider" value="0" min="0" max="0" />
        </p>
    </div>
</div>
</body>
</html>
